using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace PointOfSale.Configuration.Unit
{
	public class ListViewDetail : ListView
	{
		public delegate void ListViewContentClickHandler( object sender, ListViewContentClickEventArgs e );		

		public class ListViewContentClickEventArgs : EventArgs
		{
			public int RowIndex;
			public int ColumnIndex;
			public ListViewItem Item;

			public ListViewContentClickEventArgs( int rowIndex, int columnIndex, ListViewItem item )
			{
				RowIndex = rowIndex;
				ColumnIndex = columnIndex;
				Item = item;
			}
		}

		[StructLayout(LayoutKind.Sequential)] struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}

		[DllImport("user32.dll")]
		private static extern int SendMessage(IntPtr hWnd,
			int wMsg , int wParam , ref RECT lParam);

		[Description("Occurs when user clicks some content in ListView"), Category("ListViewDetail")]
		public event ListViewContentClickHandler ContentClick;

		private Font checkMarkFont = new Font("Marlett", 11);

		public ListViewDetail()
		{
			this.View = View.Details;
			this.MultiSelect = false;
			this.FullRowSelect = true;
			this.MouseUp += new MouseEventHandler( OnMouseUp );
		}

		/// <summary>
		/// Add a checked subitem to ListViewItem
		/// </summary>
		/// <param name="item">Item to which a SubItem is added</param>
		/// <param name="val">Check state</param>
		public void AddCheckedSubItem( ListViewItem item, bool val )		
		{
			item.SubItems.Add("");
			this.SetCheck( item, item.SubItems.Count - 1, val );
		}

		/// <summary>
		/// Sets the check state of the SubItem
		/// </summary>
		/// <param name="item">ListView item which contains the SubItem</param>
		/// <param name="columnIndex">Column index of the SubItem</param>
		/// <param name="val">Check state</param>
		public void SetCheck( ListViewItem item, int columnIndex, bool val )
		{			
			item.SubItems[ columnIndex ].Font = checkMarkFont;
			item.UseItemStyleForSubItems = false;
			item.SubItems[ columnIndex ].Text = val ? "b" : "";
		}

		/// <summary>
		/// Returns SubItems check state
		/// </summary>				
		public bool IsChecked( ListViewItem.ListViewSubItem subItem )
		{
			return (subItem.Text == "b");
		}

		private void OnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if( this.SelectedItems.Count == 0 ) return;			
			int columnIndex = GetListViewSubItem( new Point( e.X, e.Y ) );			
			if( columnIndex == -1 ) return;

			FireContentClick( this.SelectedItems[0].Index, columnIndex, this.SelectedItems[0] );
		}

		private void FireContentClick( int rowIndex, int columnIndex, ListViewItem item )
		{
			if( ContentClick != null ) 
				ContentClick( this, new ListViewContentClickEventArgs( rowIndex, columnIndex, item ) );
		}

		private int GetListViewSubItem( Point pt )
			/* from www.syncfusion.com WinForms FAQ */
		{			
			const int LVM_FIRST  = 0x1000;
			const int LVM_GETSUBITEMRECT  = (LVM_FIRST + 56);
			const int LVIR_BOUNDS = 0;
					
			RECT myrect;
			ListViewItem lvitem = this.GetItemAt(pt.X, pt.Y);
			if(lvitem == null && this.SelectedItems.Count > 0)
				lvitem = this.SelectedItems[0];

			int intLVSubItemIndex = -1;
			ListViewItem.ListViewSubItem LVSubItem = null;

			if(lvitem != null)
			{
				int intSendMessage;
				for ( int i = 1; i <= lvitem.SubItems.Count - 1; i++)
				{
					LVSubItem = lvitem.SubItems[i];
					myrect = new RECT();
					myrect.top = i;
					myrect.left = LVIR_BOUNDS;
					intSendMessage = SendMessage(this.Handle, LVM_GETSUBITEMRECT,
						lvitem.Index, ref myrect);
					if (pt.X < myrect.left)
					{
						LVSubItem = lvitem.SubItems[0];
						intLVSubItemIndex = 0;
						break;
					}
					else if (pt.X >= myrect.left & pt.X <= myrect.right)
					{
						intLVSubItemIndex = i;
						break;
					}
					else
						LVSubItem = null;
				}
			}
			if (LVSubItem == null || lvitem == null)
			{
				intLVSubItemIndex = -1;
			}
			return intLVSubItemIndex;
		}

	}

}
